package com.xuruzi.demo.util;


import com.qq.weixin.mp.aes.SHA1;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by xuruzi on 2020/3/26.
 */
public class WxUtils {
    private static final Logger logger = LoggerFactory.getLogger(WxUtils.class);
//    private static String corpId = "wwaf33d4a5baeefd0b";
//    private static String agentid = "1000005";
//    private static String redirectUri = "http://zwwx.ixuduoduo.com/loginQrCode";
//    private static String domain = "qyapi.weixin.qq.com";//微信服务器地址
//    private static String agentSecret = "o7N9oQSzfMshsm0KvNKT2KO09ngqLGrqNXNaNd7ltgM";
//    private static String token = "xuruzi";//消息接收token 自定义
//    private static String sEncodingAESKey = "UPxPwGkkcF2K4B3qw7YYC4f6Fr9SgPk9qBBB2xMIFye";


    private static String corpId = "ww39edd66a67abebf8";
    private static String agentid = "1000009";
    private static String redirectUri = "http://zwwx.ixuduoduo.com/loginQrCode";
    private static String domain = "qyapi.weixin.qq.com";//微信服务器地址
    private static String agentSecret = "TiVraRVvM7RW7qcp6FpKK_XBmaMs4pvEIRf3Zo4qaCI";
    private static String token = "xuruzi";//消息接收token 自定义
    private static String sEncodingAESKey = "KpqJrSFdHTYkMsgFduHdPi4gc9GfRuBlilR1WYAcKl7";

    /**
     * url地址进行encode
     * @param
     * @return
     * @throws Exception
     */
    public static String getEncodeUrl() throws Exception{
        return URLEncoder.encode(redirectUri,"UTF-8");
    }

    public static String getCorpId(){
        return corpId;
    }

    public static String getAgentid(){
        return agentid;
    }

    public static String getDomain(){
        return domain;
    }

    public static String getAgentSecret(){
        return agentSecret;
    }

    public static String getToken() {
        return token;
    }

    public static String getsEncodingAESKey() {
        return sEncodingAESKey;
    }


    /**
     *
     * @return
     */
    public static Map<String,Object> parseXml(HttpServletRequest request){
        HashMap map = new HashMap();
        Object inputStream = null;
        try {
            inputStream = request.getInputStream();
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            copy((InputStream)inputStream,byteStream);
            String reader = byteStream.toString();
            logger.info("接收到密文===={}",reader);

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            StringReader sr = new StringReader(reader);
            InputSource is = new InputSource(sr);
            Document document = db.parse(is);
            Element root = document.getDocumentElement();
            NodeList nodelist1 = root.getElementsByTagName("Encrypt");
            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, sEncodingAESKey, corpId);
            String msgSignature = request.getParameter("msg_signature");
            String timeStamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            logger.info("msgSignature:{}", msgSignature);
            logger.info("timeStamp:{}", timeStamp);
            logger.info("nonce:{}", nonce);
            String encrypt = nodelist1.item(0).getTextContent();
            String fromXML = String.format("<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>", new Object[]{encrypt});
            //解密后的明文内容
            String message = wxcpt.DecryptMsg(msgSignature, timeStamp, nonce, fromXML);
            logger.info("解密后的明文内容===={}",message);

            //将xml内容解析后存入map
            inputStream = new ByteArrayInputStream(message.getBytes());
            XMLInputFactory e1 = XMLInputFactory.newInstance();
            XMLEventReader reader1 = e1.createXMLEventReader((InputStream)inputStream);
            while(reader1.hasNext()) {
                XMLEvent event1 = reader1.nextEvent();
                if(event1.isStartElement()) {
                    String tagName1 = event1.asStartElement().getName().toString();
                    if("SendPicsInfo".equals(tagName1)) {
                        map.put(tagName1, eventSendPicsInfo(reader1));
                    } else if("SendLocationInfo".equals(tagName1)) {
                        map.put(tagName1, eventSendLocationInfo(reader1));
                    } else if("ScanCodeInfo".equals(tagName1)) {
                        map.put(tagName1, eventScanCodePush(reader1));
                    } else if(!"xml".equals(tagName1)) {
                        map.put(tagName1, reader1.getElementText());
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if (inputStream != null) {
                    ((InputStream) inputStream).close();
                }
            }catch (IOException e1){
                e1.printStackTrace();
            }
        }
        return map;
    }

    public static int copy(InputStream in, OutputStream out) throws IOException {
        int byteCount = 0;

        int bytesRead1;
        for(byte[] buffer = new byte[4096]; (bytesRead1 = in.read(buffer)) != -1; byteCount += bytesRead1) {
            out.write(buffer, 0, bytesRead1);
        }

        out.flush();
        return byteCount;
    }

    protected static Map<String, Object> eventSendPicsInfo(XMLEventReader reader) throws XMLStreamException {
        HashMap sendPicsInfoMap = new HashMap();

        while(true) {
            while(true) {
                XMLEvent event;
                do {
                    if(!reader.hasNext()) {
                        return sendPicsInfoMap;
                    }

                    event = reader.nextEvent();
                } while(!event.isStartElement());

                String tagName = event.asStartElement().getName().toString();
                if("Count".equals(tagName)) {
                    sendPicsInfoMap.put(tagName, reader.getElementText());
                } else if("PicList".equals(tagName)) {
                    ArrayList picList = new ArrayList();

                    while(reader.hasNext()) {
                        XMLEvent event1 = reader.nextEvent();
                        if(event1.isStartElement() && "PicMd5Sum".equals(event1.asStartElement().getName().toString())) {
                            HashMap picMap = new HashMap();
                            picMap.put("PicMd5Sum", reader.getElementText());
                            picList.add(picMap);
                        } else if(event1.isEndElement() && "PicList".equals(event1.asEndElement().getName().toString())) {
                            break;
                        }
                    }

                    sendPicsInfoMap.put(tagName, picList);
                }
            }
        }
    }

    protected static Map<String, Object> eventSendLocationInfo(XMLEventReader reader) throws XMLStreamException {
        HashMap sendLocationInfo = new HashMap();

        while(reader.hasNext()) {
            XMLEvent event = reader.nextEvent();
            if(event.isStartElement()) {
                String tagName = event.asStartElement().getName().toString();
                sendLocationInfo.put(tagName, reader.getElementText());
            }
        }

        return sendLocationInfo;
    }

    protected static Map<String, Object> eventScanCodePush(XMLEventReader reader) throws XMLStreamException {
        HashMap scanCodePush = new HashMap();

        while(reader.hasNext()) {
            XMLEvent event = reader.nextEvent();
            if(event.isStartElement()) {
                String tagName = event.asStartElement().getName().toString();
                scanCodePush.put(tagName, reader.getElementText());
            }
        }

        return scanCodePush;
    }

    /**
     * 校验url
     * @param request
     * @return
     */
    public static boolean checkSignature(HttpServletRequest request){
        try {
//            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WxUtils.getToken(), WxUtils.getsEncodingAESKey(), WxUtils.getCorpId());
            String msgSignature = request.getParameter("msg_signature");
            String timestamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            String echostr = request.getParameter("echostr");
            String signature = SHA1.getSHA1(token, timestamp, nonce, echostr);
            if (!signature.equals(msgSignature)) {
                return false;
            }
        }catch (Exception e){

        }
        return true;
    }
}
